﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Diagnostics;

namespace SmartFront.Toolkit.Core
{
    /// <summary>
    /// Object Comparer which can compare two object 
    /// and underlying type which had implemented IComparable
    /// </summary>
    public sealed class ObjectComparer : IComparer<object>
    {
        #region IComparer<object> Members

        /// <summary>
        /// Compares two objects and returns a value indicating whether one is less than, equal to, or greater than the other.
        /// </summary>
        /// <param name="x">The first object to compare.</param>
        /// <param name="y">The second object to compare.</param>
        /// <returns>
        /// Value
        /// Condition
        /// Less than zero
        /// <paramref name="x"/> is less than <paramref name="y"/>.
        /// Zero
        /// <paramref name="x"/> equals <paramref name="y"/>.
        /// Greater than zero
        /// <paramref name="x"/> is greater than <paramref name="y"/>.
        /// </returns>
        public int Compare(object x, object y)
        {
            //If Both objects are null than they are equal
            if ((x == null && y == null) || (x is DBNull && y is DBNull))
            {
                return 0;
            }
            //If Only x is null than its lesser than y
            if (x == null || x is DBNull)
            {
                return -1;
            }
            //if only y is null than its lesser than x
            if (y == null || y is DBNull)
            {
                return 1;
            }
            //Both are not null than check if they are .NET type 
            //which generally implements IComparable
            //Compare them with it.
            if (x.GetType() == y.GetType())
            {
                IComparable comparable = x as IComparable;
                if (null != comparable)
                {
                    return comparable.CompareTo(y);
                }
            }

            //Check equality based on object reference
            //If they are equal than they are same objects.
            if (Object.ReferenceEquals(x, y) || x.Equals(y))
            {
                return 0;
            }

            //Both are equal and we can not perform comparision here
            Debug.WriteLine(String.Format("x - {0} and y - {1} are not comparable", x, y));
            //Safely return true and make them equal, failure on comparision.
            return 0;
        }

        #endregion
    }
}
